package com.zhiyou.aifeng.common.helper

import android.os.Build
import android.text.Html
import android.text.Spanned
import android.widget.TextView
import org.json.JSONObject
import java.text.DecimalFormat
import java.util.*
import java.util.regex.Pattern

fun TextView?.toUpperCase(): String = textString().toUpperCase(Locale.getDefault())

fun TextView?.textString(): String =
    when {
        this == null -> ""
        else -> text.toString()
    }

fun TextView?.trimString(): String =
    when {
        this == null -> ""
        else -> text.trimString()
    }

fun TextView?.trimStartString(): String =
    when {
        this == null -> ""
        else -> text.trimStartString()
    }

fun TextView?.trimEndString(): String =
    when {
        this == null -> ""
        else -> text.trimEndString()
    }

fun TextView?.trimToUpperCase(): String =
    when {
        this == null -> ""
        else -> text.trimToUpperCase()
    }

fun CharSequence?.trimString(): String =
    when {
        this@trimString.isNullOrEmpty() -> ""
        else -> trim().toString()
    }

fun CharSequence?.trimStartString(): String =
    when {
        this@trimStartString.isNullOrEmpty() -> ""
        else -> trimStart().toString()
    }

fun CharSequence?.trimEndString(): String =
    when {
        this@trimEndString.isNullOrEmpty() -> ""
        else -> trimEnd().toString()
    }

fun CharSequence?.trimToUpperCase(): String =
    when {
        this@trimToUpperCase.isNullOrEmpty() -> ""
        else -> trim().toString().toUpperCase(Locale.getDefault())
    }

fun CharSequence?.toTextInt(): Int = toString().toNotInt()
fun CharSequence?.toTextLong(): Long = toString().toNotLong()
fun CharSequence?.toTextFloat(): Float = toString().toNotFloat()
fun CharSequence?.toTextDouble(): Double = toString().toNotDouble()

fun String?.toNotInt(): Int =
    when {
        this@toNotInt.isNullOrEmpty() -> 0
        else -> toInt()
    }

fun String?.toNotLong(): Long =
    when {
        this@toNotLong.isNullOrEmpty() -> 0L
        else -> toLong()
    }

fun String?.toNotFloat(): Float =
    when {
        this@toNotFloat.isNullOrEmpty() -> "0".toFloat()
        else -> toFloat()
    }

fun String?.toNotDouble(): Double =
    when {
        this@toNotDouble.isNullOrEmpty() -> "0".toDouble()
        else -> toDouble()
    }

/**
 * flags:
 *    FROM_HTML_MODE_COMPACT：html块元素之间使用一个换行符分隔
 *    FROM_HTML_MODE_LEGACY： html块元素之间使用两个换行符分隔
 */
@Suppress("DEPRECATION")
fun fromHtmlEx(source: String): Spanned =
    when {
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ->
            Html.fromHtml(
                source,
                Html.FROM_HTML_MODE_LEGACY
            )
        else -> Html.fromHtml(source)
    }

/**
 * Returns the value mapped by name if it exists, coercing it if
 * necessary, or fallback if no such mapping exists or empty.
 */
inline fun <reified T : JSONObject> T?.optNotEmpty(
    name: String,
    defaultValue: String
): String =
    when {
        this == null -> defaultValue
        isNull(name) || optString(name).isEmpty() -> defaultValue
        else -> optString(name, defaultValue)
    }

inline fun <reified T : JSONObject> T?.optNotNull(
    name: String,
    defaultValue: String = ""
): String =
    when {
        this == null -> defaultValue
        isNull(name) -> defaultValue
        else -> optString(name, defaultValue)
    }

/**
 * 姓名* 替换，保留姓氏
 * 如果姓名为空 或者 null ,返回空 ；否则，返回替换后的字符串；
 */
fun String?.nameReplaceWithStar(): String =
    when {
        this@nameReplaceWithStar.isNullOrEmpty() -> ""
        else -> replaceAction("(?<=[\\u4e00-\\u9fa5]{" + (if (length > 3) "2" else "1") + "})[\\u4e00-\\u9fa5](?=[\\u4e00-\\u9fa5]{0})")
    }

/**
 * 手机号* 替换，保留前三位和后四位
 * 如果手机号为空 或者 null ,返回空 ；否则，返回替换后的字符串；
 */
fun String?.phoneReplaceWithStar(): String =
    when {
        this@phoneReplaceWithStar.isNullOrEmpty() -> ""
        length < 7 -> this
        else -> replaceAction("(?<=\\d{3})\\d(?=\\d{4})")
    }

/**
 * 身份证号* 替换，保留前四位和后四位
 * 如果身份证号为空 或者 null ,返回空 ；否则，返回替换后的字符串；
 */
fun String?.idCardReplaceWithStar(): String =
    when {
        this@idCardReplaceWithStar.isNullOrEmpty() -> ""
        length < 8 -> this
        else -> replaceAction("(?<=\\d{4})\\d(?=\\d{4})")
    }

/**
 * 银行卡* 替换，保留后四位
 * 如果银行卡号为空 或者 null ,返回空 ；否则，返回替换后的字符串；
 */
fun String?.bankCardReplaceWithStar(): String =
    when {
        this@bankCardReplaceWithStar.isNullOrEmpty() -> ""
        length < 4 -> this
        else -> replaceAction("(?<=\\d{0})\\d(?=\\d{4})")
    }

/**
 * 银行卡* 替换，保留前六位和后四位
 * 如果银行卡号为空 或者 null ,返回空 ；否则，返回替换后的字符串；
 */
fun String?.bankCardReplaceHeaderWithStar(): String =
    when {
        this@bankCardReplaceHeaderWithStar.isNullOrEmpty() -> ""
        length < 10 -> this
        else -> replaceAction("(?<=\\d{6})\\d(?=\\d{4})")
    }

/**
 * 实际替换动作
 */
fun String?.replaceAction(regular: String): String =
    when {
        this@replaceAction.isNullOrEmpty() -> ""
        else -> replace(regular.toRegex(), "*")
    }

/**
 * 判断字符串是否为整数和小数
 */
fun CharSequence?.isNumeric(): Boolean =
    when {
        this@isNumeric.isNullOrEmpty() -> false
        else -> {
            val regex = "-?[0-9]+.?[0-9]+"
            val pattern = Pattern.compile(regex)
            pattern.matcher(this).matches()
        }
    }

/**
 * 校验密码是否6~20位字母加数字
 */
fun CharSequence?.isPasswordWithAndNumber(): Boolean =
    when {
        this@isPasswordWithAndNumber.isNullOrEmpty() -> false
        else -> {
            val regex = "^(?!\\d+\$)(?![a-zA-Z]+\$)[0-9A-Za-z]{6,20}\$"
            val pattern = Pattern.compile(regex)
            pattern.matcher(this).matches()
        }
    }

/**
 * 车牌号校验（含新能源车牌）
 */
fun CharSequence?.isCarNumber(): Boolean =
    when {
        this@isCarNumber.isNullOrEmpty() -> false
        length < 6 -> false
        else -> {
            // val regex = "^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))\$"
            val regex =
                "^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼](([A-HJ-Z][A-HJ-NP-Z0-9]{5})|([A-HJ-Z](([DF][A-HJ-NP-Z0-9][0-9]{4})|([0-9]{5}[DF])))|([A-HJ-Z][A-D0-9][0-9]{3}警)))|([0-9]{6}使)|((([沪粤川云桂鄂陕蒙藏黑辽渝]A)|鲁B|闽D|蒙E|蒙H)[0-9]{4}领)|(WJ[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼·•][0-9]{4}[TDSHBXJ0-9])|([VKHBSLJNGCE][A-DJ-PR-TVY][0-9]{5}))\$"

            val pattern = Pattern.compile(regex)
            pattern.matcher(this).matches()
        }
    }

/**
 * 手机号校验
 */
fun CharSequence?.isMobile(): Boolean =
    when {
        this@isMobile.isNullOrEmpty() -> false
        length != 11 -> false
        else -> {
            val regex =
                "^((1[3|5|8][0-9])|(14[5|7])|(16[6])|(17[0|1|3|5|6|7|8])|(19[0|2|6|7|8|9]))\\d{8}$"
            val pattern = Pattern.compile(regex)
            pattern.matcher(this).matches()
        }
    }

/**
 * 传真校验
 */
fun CharSequence?.isFax(): Boolean =
    when {
        this@isFax.isNullOrEmpty() -> false
        else -> {
            val regex = "^((\\d{7,8})|(0\\d{2,3}-\\d{7,8}))\$"
            val pattern = Pattern.compile(regex)
            pattern.matcher(this).matches()
        }
    }

/**
 * 固话校验
 */
fun CharSequence?.isTel(): Boolean =
    when {
        this@isTel.isNullOrEmpty() -> false
        else -> {
            val regex =
                "^((\\d{7,8})|(0\\d{2,3}-\\d{7,8})|(400-\\d{3}-\\d{4})|(1[3456789]\\d{9}))$" //固话（含区号）、400固话、匹配手机

            /*val reg = "(?:(\\(\\+?86\\))(0[0-9]{2,3}\\-?)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?)|" +
                    "(?:(86-?)?(0[0-9]{2,3}\\-?)?([2-9][0-9]{6,7})+(\\-[0-9]{1,4})?)";*/

            val pattern = Pattern.compile(regex)
            pattern.matcher(this).matches()
        }
    }

/**
 * 邮箱校验
 */
fun CharSequence?.isEmail(): Boolean =
    when {
        this@isEmail.isNullOrEmpty() -> false
        else -> {
            // val regex = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"
            val regex =
                "^\\s*\\w+(?:\\.?[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$"

            val pattern = Pattern.compile(regex)
            pattern.matcher(this).matches()
        }
    }

/**
 * 网址校验
 */
fun CharSequence?.isWeb(): Boolean =
    when {
        this@isWeb.isNullOrEmpty() -> false
        else -> {
            val regex =
                "(http://|ftp://|https://|www)?[^\u4e00-\u9fa5\\s]*?\\.(com|net|cn|me|tw|fr)[^\u4e00-\u9fa5\\s]*"

            // val regex = "^([hH][tT]{2}[pP]:/*|[hH][tT]{2}[pP][sS]:/*|[fF][tT][pP]:/*)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\\/])+(\\?{0,1}(([A-Za-z0-9-~]+\\={0,1})([A-Za-z0-9-~]*)\\&{0,1})*)$"

            val pattern = Pattern.compile(regex)
            pattern.matcher(this).matches()
        }
    }

/**
 * 将中文转为Unicode
 */
fun String?.encodeUnicode(): String =
    when {
        this@encodeUnicode.isNullOrEmpty() -> ""
        else -> {
            val unicodeBytes = StringBuilder()
            toCharArray().forEach {
                //转换为十六进制整型字符串
                val hexB = Integer.toHexString(it.toInt())
                unicodeBytes
                    .append("\\u")
                    .append(hexB.padStart(4, '0'))
            }

            unicodeBytes.toString()
        }
    }

/**
 * 将Unicode转为中文
 */
fun String?.decodeUnicode(): String =
    when {
        this@decodeUnicode.isNullOrEmpty() -> ""
        else -> {
            var start = 0
            var end: Int
            val buffer = StringBuilder()
            while (start > -1) {
                end = indexOf("\\u", start + 2)
                val charStr = substring(start + 2 until if (end == -1) length else end)
                //十六进制解析为整形字符串
                val letter = Integer.parseInt(charStr, 16).toChar()
                buffer.append(letter.toString())
                start = end
            }

            buffer.toString()
        }
    }

/**
 * 浮点类型保留两位有效小数（四舍五入）；
 */
fun Double?.formatDecimal(): String =
    when {
        this == null -> DecimalFormat("########0.00").format(0.00)
        else -> DecimalFormat("########0.00").format(this)
    }

/**
 * 浮点类型保留最多两位（最少0位）有效小数（四舍五入）；
 */
fun Double?.formatDecimalWhenHave(
    default: String = "0",
    zeroValue: String = "0"
): String =
    when {
        this == null -> default
        this == 0.00 -> zeroValue
        else -> DecimalFormat("########0.##").format(this)
    }

/**
 * 字符串类型浮点数保留两位有效小数（四舍五入）；
 */
fun String?.formatDecimal(): String =
    when {
        isNullOrEmpty() -> "0.00"
        else -> DecimalFormat("########0.00").format(toNotDouble())
    }

/**
 * 字符串类型浮点数保留最多两位（最少0位）有效小数（四舍五入）；
 */
fun String?.formatDecimalWhenHave(
    default: String = "0",
    zeroValue: String = "0"
): String =
    when {
        isNullOrEmpty() -> default
        toNotDouble() == 0.00 -> zeroValue
        else -> DecimalFormat("########0.##").format(toNotDouble())
    }

/**
 * 字符串类型浮点数保留整数部分（四舍五入）；
 */
fun String?.formatInteger(
    default: String = "0",
    zeroValue: String = "0"
): String =
    when {
        isNullOrEmpty() -> default
        toNotDouble() == 0.00 -> zeroValue
        else -> DecimalFormat("########0").format(toNotDouble())
    }

/**
 * 格式化数字为千分位，浮点型则保留两位有效数字；
 */
fun String?.formatNumber(default: String = ""): String =
    when {
        this@formatNumber.isNullOrEmpty() -> default
        else -> {
            val df = when {
                "." in this -> DecimalFormat("###,##0.00")
                else -> DecimalFormat("###,###,###")
            }
            df.format(toDouble())
        }
    }

fun String?.formatBankcard(pattern: String = "  "): String =
    when {
        this@formatBankcard.isNullOrEmpty() -> ""
        else -> {
            val stringBuilder = StringBuilder()
            forEachIndexed { index, char ->
                stringBuilder.append(char)
                if ((index + 1) % 4 == 0) stringBuilder.append(pattern)
            }
            stringBuilder.toString()
        }
    }